package com.wenqiner.requesttool.util;

import cn.hutool.core.text.CharSequenceUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONWriter;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wenqiner.requesttool.core.exception.CustomException;

import java.util.Collection;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;

/**
 * 数字签名工具类
 *
 * @author: rhf
 * @DATE: 2022-06-08
 **/
public class DigitalSignatureUtil {
    public static ObjectMapper objectMapper = ObjectMapperUtil.getMapper();

    private DigitalSignatureUtil() {
    }

    /**
     * 生成签名
     *
     * @param originJsonStr    原始json串
     * @param key              私钥
     * @param suffixCharacters 其他参数
     * @date 2022/6/8
     */
    public static String createSign(String originJsonStr, String key, String... suffixCharacters) throws Exception {
        String paramCharacter = ascSort(originJsonStr);
        return sign(key, paramCharacter, suffixCharacters);
    }

    /**
     * 拼接上参数后形成加密原串
     *
     * @param originJsonStr    原始json字符串
     * @param suffixCharacters 其他参数
     * @return java.lang.String
     * @date 2022/6/8
     */
    @SuppressWarnings("unused")
    public static String ascSort(String originJsonStr, String... suffixCharacters) throws JsonProcessingException {
        String s = ascSort(originJsonStr);
        String suffixCharacter = String.join("", suffixCharacters);
        return s + suffixCharacter;
    }

    /**
     * 以 key=val&key1=val1... 格式拼接
     *
     * @param originJsonStr 原始json字符串
     * @return java.lang.String
     * @date 2022/6/8
     */
    public static String ascSort(String originJsonStr) throws JsonProcessingException {
        if (CharSequenceUtil.isBlank(originJsonStr)) {
            return "";
        }

        Map<String, Object> map = convertMap(originJsonStr);
        if (null == map) {
            return "";
        }

        String ascStr = map.keySet().stream().map(key -> {
            Object o = map.get(key);
            if (null != o) {
                if (o instanceof Map || o instanceof Collection) {
                    try {
                        o = ascSortDeserializer(o);
                    } catch (JsonProcessingException e) {
                        throw new CustomException("数据排序异常");
                    }
                }
                return String.join("", key, "=", o.toString(), "&");
            } else {
                return "";
            }
        }).collect(Collectors.joining());

        return CharSequenceUtil.isNotBlank(ascStr) ? ascStr.substring(0, ascStr.length() - 1) : originJsonStr;
    }

    /**
     * 以 key=val&key1=val1... 格式拼接
     *
     * @param originJsonStr 原始json字符串
     * @return java.lang.String
     * @author rhf
     */
    public static String aliAcsSort(String originJsonStr) {
        if (CharSequenceUtil.isBlank(originJsonStr)) {
            return "";
        }
        Map<String, Object> map = JSON.parseObject(originJsonStr, TreeMap.class);
        String ascStr = map.keySet().stream().map(key -> {
            Object o = map.get(key);
            if (null != o) {
                if (o instanceof Map || o instanceof Collection) {
                    o = JSON.toJSONString(o, JSONWriter.Feature.MapSortField);
                }
                return String.join("", key, "=", o.toString(), "&");
            } else {
                return "";
            }
        }).collect(Collectors.joining());

        return CharSequenceUtil.isNotBlank(ascStr) ? ascStr.substring(0, ascStr.length() - 1) : originJsonStr;
    }

    /**
     * 序列化排序
     *
     * @param value jsonStr
     * @return java.lang.String
     * @date 2022/6/10
     */
    private static String ascSortDeserializer(Object value) throws JsonProcessingException {
        return objectMapper.writeValueAsString(value);
    }

    /**
     * convert obj to map
     *
     * @param reqJsonStr json
     * @return java.util.Map<java.lang.String, java.lang.Object>
     * @date 2022/6/20
     */
    private static TreeMap convertMap(String reqJsonStr) throws JsonProcessingException {
        return objectMapper.readValue(reqJsonStr, TreeMap.class);
    }

    /**
     * @param key              私钥
     * @param paramCharacter   原串
     * @param suffixCharacters 其他参数
     * @return java.lang.String
     * @author rhf
     */
    private static String sign(String key, String paramCharacter, String... suffixCharacters) throws Exception {
        if (null != suffixCharacters) {
            paramCharacter = paramCharacter.concat(String.join("", suffixCharacters));
        }
        return RSAUtil.sign(key, paramCharacter);
    }
}
